package gitobject;

import java.io.*;

import core.JitBranch;
import sha1.SHA1;
import repository.Repository;

public class Commit extends GitObject{
    protected String tree; 		// the sha1 value of present committed tree
    protected String parent; 	// the sha1 value of the parent commit
    protected String author; 	// the author's name and timestamp
    protected String committer; // the committer's info
    protected String message; 	// the commit memo

    public String getParent(){return parent;}
    public String getTree(){return tree;}
    public String getAuthor(){return author;}
    public String getCommitter(){return committer;}
    public String getMessage(){return message;}
    //private static final long serialVersionUID = 1L;
    public Commit(){}
    /**
     * Construct a commit directly from a file.
     * @param
     * author, committer, message参数在git commit命令里创建
     * @throws Exception
     */
    public Commit(String treePath, String author, String committer, String message) throws Exception {
        this.fmt = "commit"; 	//type of object
        this.tree = new Tree(new File(treePath)).getKey(); 
        this.parent = getLastCommit() == null ? "" : getLastCommit(); //null means there is no parent commit.
        this.author = author;
        this.committer = committer;
        this.message = message;

        /*Content of this commit, like this:
         *tree bd31831c26409eac7a79609592919e9dcd1a76f2
         *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
         *author xxx  1502331401 +0800
         *committer xxx  1502331401 +0800
         *修复增量bug
         * */
        this.value = "tree " + this.tree + "\nparent " + this.parent+ "\nauthor " + this.author + "\ncommitter " + this.committer + "\n" + this.message;
        key = genKey();
        if(JitBranch.getCurBranch().exist()){
            BufferedWriter out = new BufferedWriter(new FileWriter(Repository.getGitDir()  + File.separator + "refs"
                    + File.separator + "heads" + File.separator + JitBranch.getCurBranch().branchName));
            out.write(key); // Record the hash value of the latest commit. (Overlay)
            out.close();
        }
        else{

            BufferedWriter out = new BufferedWriter(new FileWriter(Repository.getGitDir()  + File.separator + "refs"
                    + File.separator + "heads" + File.separator + "master"));
            out.write(key); // Record the hash value of the latest commit. (Overlay)
            out.close();
        }
        compressWrite();

    }
    
    /**
     * Construct a commit from a built tree.
     * @param
     * author, committer, message参数在git commit命令里创建
     * @throws Exception
     */
    public Commit(Tree t, String author, String committer, String message) throws Exception {
        this.fmt = "commit"; 	//type of object
        this.tree = t.getKey(); 
        this.parent = getLastCommit() == null ? "" : getLastCommit(); //null means there is no parent commit.
        this.author = author;
        this.committer = committer;
        this.message = message;

        /*Content of this commit, like this:
         *tree bd31831c26409eac7a79609592919e9dcd1a76f2
         *parent d62cf8ef977082319d8d8a0cf5150dfa1573c2b7
         *author xxx  1502331401 +0800
         *committer xxx  1502331401 +0800
         *修复增量bug
         * */
        this.value = "tree " + this.tree + "\nparent " + this.parent+ "\nauthor " + this.author + "\ncommitter " + this.committer + "\n" + this.message;
        key = genKey();
        String branchPath = Repository.getGitDir()  + File.separator + "refs" + File.separator + "heads" + File.separator + "master";
        File masterFile = new File(branchPath);
        if(masterFile.exists()){
            BufferedWriter out = new BufferedWriter(new FileWriter(Repository.getGitDir()  + File.separator + "refs"
                    + File.separator + "heads" + File.separator + JitBranch.getCurBranch().branchName));
            out.write(key); // Record the hash value of the latest commit. (Overlay)
            out.close();
        }
        else{

            BufferedWriter out = new BufferedWriter(new FileWriter(Repository.getGitDir()  + File.separator + "refs"
                    + File.separator + "heads" + File.separator + "master"));
            out.write(key); // Record the hash value of the latest commit. (Overlay)
            out.close();
        }
        writeObject();
    }
    
    /**
     * Deserialize the commit object from its key(commitId)
     * @param commitId
     * @throws IOException
     */
    public static Commit deserialize(String commitId)  {
        if(commitId != null && commitId.length()!=0){
            try{
                String commitObjPath = Repository.getGitDir() + File.separator + "objects" +
                        File.separator + commitId.substring(0,2) + File.separator + commitId.substring(2);
                //System.out.println(commitObjPath);
                File objDirectory = new File(commitObjPath);
                //System.out.println(objDirectory.exists());
                if(objDirectory.exists()){
                    ObjectInputStream objInput = new ObjectInputStream(new FileInputStream(objDirectory));
                    Commit commit = (Commit)objInput.readObject();
                    //System.out.println(commit.getValue());
                    return commit;
                }

            }catch(Exception e){
                e.printStackTrace();
            }
        }
        return null; // cannot find Commit Object
    }

    /**
     * Generate the hash value of this commit.
     * @return key
     * */
    public String genKey() throws Exception {
        key = SHA1.getHash(value);
        return key;
    }

    /**
     * Get the parent commit from the HEAD file.
     * @return
     * @throws IOException
     */
    public static String getLastCommit() throws IOException {

        File HEAD = new File(Repository.getGitDir() + File.separator + "HEAD");

        String path = getValue(HEAD).substring(5).replace("\n", "");
        path = path.replace("/",File.separator);

        File branchFile = new File(Repository.getGitDir() + File.separator + path);

        if (branchFile.isFile()) {

            return getValue(branchFile);
        } else {

            return null;
        }
    }

    /**
     * Judge whether two commits are equal
     * @param obj
     * @return isEqual
     */
    public boolean isEquals(Commit obj) {
        boolean isEqual = false;
        if(this == null && obj == null)
            isEqual = true;
        else if(this == null || obj == null)
            isEqual =  false;
        else{
            if(this.getTree().equals(obj.getTree()) && this.getParent().equals(obj.getParent())
                    && this.getAuthor().equals(obj.getAuthor()) && this.getCommitter().equals(obj.getCommitter())
                    && this.getMessage().equals(obj.getMessage()))

                isEqual = true;
        }
        return isEqual;

    }
}

